<?php

namespace W3;

/**
 * 负责框架内类的自动加载
 *
 * @author edikud
 * @date 2022/10/22
 * @copyright Copyright (c) 2022 W3 (http://www.mcooo.com)
 * @license GNU General Public License 2.0
 */

class Loader
{
    /**
     * 类别名数组
     *
     * @var array
     */
    protected static $aliases = [];
	
    /**
     * 映射类
     *
     * @var array
     */
    protected static $classes = [];

    /**
     * PSR-0目录
     *
     * @var array
     */
    protected static $directories = [];

    /**
     * 禁止构造函数 (静态类)
     *
     * @access  protected
     */
    protected function __construct()
    {
        // Nothing here
    }

    /**
     * 映射类加载器
     *
     *  <code>
     *      static::classes('name', ['ClassName', 'path\to\class']);
     *  </code>
     *
     * @access  public
     * @param string|array $name 类名
     * @param string $class 类的路径
     */
    public static function classes($name, $class = NULL)
    {
        if ( ! is_array($name)) {
            $name = [$name => $class];
        }

        foreach ($name as $key => $val)
		{
            static::$classes[$key] = $val;
        }
    }

    /**
     * 映射类别名
     *
     * @param string[]|string $name
     *
     * @return void
     */
    public static function aliases($name, $class = NULL)
    {
        if ( ! is_array($name)) {
            $name = [$name => $class];
        }

        foreach ($name as $key => $val)
		{
            static::$aliases[$key] = $val;
        }
    }
	
    /**
     * 将路径附加到要搜索的目录数组
     *
     * @param string[]|string $path
     *
     * @return void
     */
    public static function directory($path)
    {
        if ( ! is_array($path)) {
			$path = [$path];
        }

        foreach ($path as $val)
		{
            static::$directories[] = $val;
        }
    }

    /**
     * 尝试加载与PSR-0兼容的类
     *
     * @access  protected
     * @param  string  $className Class name
     * @param  string  $directory (Optional) Overrides the array of PSR-0 paths
     * @return boolean
     */
    protected static function loadPSR0(string $className, ?string $directory = null): bool
    {
        $classPath = str_replace(['\\', '_'], DIRECTORY_SEPARATOR, $className) . '.php';
	
        $dirs = ($directory === null) ? static::$directories : [$directory];

        foreach ($dirs as $dir) 
		{
            if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) {
                include ($dir . DIRECTORY_SEPARATOR . $classPath);

                return true;
            }
        }

        return false;
    }

    /**
     * 负责文件的加载
     *
     * @param string $class
     *
     * @return bool|mixed  
     */
    public static function load(string $className): bool
    {
        if (isset(static::$aliases[$className])) {
            return class_alias(static::$aliases[$className], $className);
        }

        if (isset(static::$classes[$className])) {
			$classPath = str_replace('\\', DIRECTORY_SEPARATOR, static::$classes[$className]) . '.php';
			if(file_exists($classPath)) {
				include $classPath;
			}

            return true;
        }

        /**
         * 尝试加载与PSR-0兼容的类
         * 
         */
        if (static::loadPSR0($className)) {
            return true;
        }

        return false;
    }
	
    /**
     * 将类加载器注册到SPL自动加载
     *
     * @return  void
     */
    public static function autoLoad()
    {
        spl_autoload_register([Loader::class, 'load'], true);
    }

}
